﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Collections.ObjectModel;
using System.IO;
using System.Windows;

namespace BDSim
{
    public class ScenarioDataProvider : BDSimDataProvider
    {
        Scenario _Parent;

        public Scenario Parent
        {
            get { return _Parent; }
            set { _Parent = value; }
        }

        Dictionary<EConstellationType, char> constellationDic = new Dictionary<EConstellationType, char>() 
        { 
            { EConstellationType.GPS, 'G' }, 
            { EConstellationType.BD, 'C' }, 
            { EConstellationType.GLONASS, 'R' }, 
            { EConstellationType.GALILEO, 'E' } 
        };

        Dictionary<ERecType, char> receiverDic = new Dictionary<ERecType, char>() 
        { 
            { ERecType.GPS, 'G' }, 
            { ERecType.BD, 'C' }, 
            { ERecType.GLONASS, 'R' }, 
            { ERecType.GALILEO, 'E' } 
        };

        public override void DefineCommand()
        {
            MenuCommand ParamConfig = new MenuCommand() { Header = "参数配置" };
            ParamConfig.DefineExcuteCommand(ParameterConfig_Execute, ParameterConfig_CanExecute);
            MenuCommandList.Add(ParamConfig);

            MenuCommand ExportData = new MenuCommand() { Header = "导出数据" };
            ExportData.DefineExcuteCommand(ExportData_Execute, ExportData_CanExecute);
            MenuCommandList.Add(ExportData);
        }

        #region 定义命令处理方法

        #region 导出数据执行方法模板
        /// <summary>
        /// ExportData功能命令执行方法
        /// </summary>
        /// <param name="param"></param>
        void ExportData_Execute(object param)
        {
            FileSaveWnd fileSave = new FileSaveWnd();
            fileSave.DlgStartSaveThread = StartSaveThread;
            MainDispatcher.DlgAddLayoutDocument(fileSave, "导出数据");
        }
        /// <summary>
        /// XXX功能命令可执行控制
        /// </summary>
        /// <param name="param"></param>
        /// <returns></returns>
        bool ExportData_CanExecute(object param)
        {
            bool flag = false;
            if (BDSimObject.GlobalStatus == ESimStatus.Inited || BDSimObject.GlobalStatus == ESimStatus.Pause)
            {
                flag = true;
            }
            return flag;
        }

        /// <summary>
        /// 启动保存数据线程
        /// </summary>
        /// <param name="dataSaveFlagModelList"></param>
        /// <param name="type"></param>
        /// <param name="path"></param>
        void StartSaveThread(ObservableCollection<DataSaveFlagModel> DataSaveFlagModelList, DataSaveType SaveType, string SavePath)
        {
            if (!Directory.Exists(SavePath))
            {
                Directory.CreateDirectory(SavePath);
            }
            switch (SaveType)
            {
                case DataSaveType.Rinex2_10格式:
                    string RinexDirectory = null;
                    if (SavePath != null)
                    {
                        DateTime NowTime = DateTime.Now;
                        string NowTimeString = NowTime.Year.ToString() + string.Format("{0:D2}", NowTime.Month) + string.Format("{0:D2}", NowTime.Day) +
                            "_" + string.Format("{0:D2}", NowTime.Hour) + "_" + string.Format("{0:D2}", NowTime.Minute) + "_" + string.Format("{0:D2}", NowTime.Second);

                        RinexDirectory = string.Format(SavePath + "\\RinexData_" + NowTimeString);
                        if (!Directory.Exists(RinexDirectory))
                        {
                            Directory.CreateDirectory(RinexDirectory);
                        }
                    }
                    foreach (var item in DataSaveFlagModelList)
                    {
                        if (item.IsChecked == true && item.IsEnable == true && item.IsVisible == System.Windows.Visibility.Visible)
                        {
                            WriteRinex210Files(RinexDirectory, item);
                        }
                    }
                    MessageBox.Show("Rinex2_10数据保存成功!", "提示", MessageBoxButton.OK, MessageBoxImage.Information);
                    // BDSimObject.DlgReportPropertyInfo("Rinex2_10数据保存成功!");
                    break;
                case DataSaveType.Rinex3_02格式:

                    string Rinex302Directory = null;
                    if (SavePath != null)
                    {
                        DateTime NowTime = DateTime.Now;
                        string NowTimeString = NowTime.Year.ToString() + string.Format("{0:D2}", NowTime.Month) + string.Format("{0:D2}", NowTime.Day) +
                            "_" + string.Format("{0:D2}", NowTime.Hour) + "_" + string.Format("{0:D2}", NowTime.Minute) + "_" + string.Format("{0:D2}", NowTime.Second);

                        Rinex302Directory = string.Format(SavePath + "\\RinexData_" + NowTimeString);
                        if (!Directory.Exists(Rinex302Directory))
                        {
                            Directory.CreateDirectory(Rinex302Directory);
                        }
                    }
                    foreach (var item in DataSaveFlagModelList)
                    {
                        if (item.IsChecked == true && item.IsEnable == true && item.IsVisible == System.Windows.Visibility.Visible)
                        {
                            WriteRinex302File(Rinex302Directory, item);
                        }
                    }
                    MessageBox.Show("Rinex3_02数据保存成功!", "提示", MessageBoxButton.OK, MessageBoxImage.Information);
                    //BDSimObject.DlgReportPropertyInfo("Rinex3_02数据保存成功!");
                    break;
                case DataSaveType.自定义格式:

                    string TextDirectory = null;
                    if (SavePath != null)
                    {
                        DateTime NowTime = DateTime.Now;

                        string NowTimeString = NowTime.Year.ToString() + string.Format("{0:D2}", NowTime.Month) + string.Format("{0:D2}", NowTime.Day) +
                            "_" + string.Format("{0:D2}", NowTime.Hour) + "_" + string.Format("{0:D2}", NowTime.Minute) + "_" + string.Format("{0:D2}", NowTime.Second);

                        TextDirectory = string.Format(SavePath + "\\TextData_{0}", NowTimeString);
                        if (!Directory.Exists(TextDirectory))
                        {
                            Directory.CreateDirectory(TextDirectory);
                        }
                    }
                    foreach (var item in DataSaveFlagModelList)
                    {
                        if (item.IsChecked == true && item.IsEnable == true && item.IsVisible == System.Windows.Visibility.Visible)
                        {
                            SaveTextData(TextDirectory, item);
                        }
                    }
                    MessageBox.Show("文本数据保存成功!", "提示", MessageBoxButton.OK, MessageBoxImage.Information);
                    //BDSimObject.DlgReportPropertyInfo("文本数据保存成功!");
                    break;
                case DataSaveType.二进制数据流格式:
                    break;
                default:
                    MessageBox.Show("请选择数据类型!", "提示", MessageBoxButton.OK, MessageBoxImage.Information);//kj,未选择数据保存类型时提示
                    break;
            }
        }

        #region ///数据保存
        /// <summary>
        /// Rinex210 数据保存总入口
        /// </summary>
        /// <param name="RinexDirectory">文件保存路经</param>
        /// <param name="DataModel">模型节点类型</param>
        /// <returns></returns>
        public bool WriteRinex210Files(string RinexDirectory, DataSaveFlagModel DataModel)
        {
            switch (DataModel.Name)
            {
                case "空间段":
                    string spaceDataDirectory = string.Format(RinexDirectory + "\\空间段");

                    //写入卫星精密星历SP3格式数据
                    if (DataModel.SubModelList[0].IsChecked)
                    {
                        if (!Directory.Exists(spaceDataDirectory))
                        {
                            Directory.CreateDirectory(spaceDataDirectory);
                        }
                        WriteRinexSP3File(spaceDataDirectory);
                    }
                    //写入卫星钟差Rinex格式数据
                    if (DataModel.SubModelList[1].IsChecked)
                    {
                        if (!Directory.Exists(spaceDataDirectory))
                        {
                            Directory.CreateDirectory(spaceDataDirectory);
                        }
                        WriteSatRinexClkFile(spaceDataDirectory);
                    }
                    break;
                case "地面控制段":
                    string StaDataDirectory = string.Format(RinexDirectory + "\\地面控制段");
                    //监测站存入观测值
                    if (DataModel.SubModelList[1].IsChecked)
                    {
                        if (!Directory.Exists(StaDataDirectory))
                        {
                            Directory.CreateDirectory(StaDataDirectory);
                        }
                        WriteRinexObserveFileV210(StaDataDirectory, ESegmentType.GroudSegment);
                    }
                    //主控站存导航电文（2016.5.5）
                    if (DataModel.SubModelList[0].IsChecked)
                    {
                        if (!Directory.Exists(StaDataDirectory))
                        {
                            Directory.CreateDirectory(StaDataDirectory);
                        }
                        //待确定
                        WriteRinexNavMesgFile(StaDataDirectory, DataSaveType.Rinex2_10格式);
                    }
                    //所有站存钟差（2016.5.5）
                    if (DataModel.SubModelList[0].IsChecked)
                    {
                        if (!Directory.Exists(StaDataDirectory))
                        {
                            Directory.CreateDirectory(StaDataDirectory);
                        }
                        //待确定
                        WriteStationRinexClkFile(StaDataDirectory);
                    }
                    break;
                case "用户段":
                    string UserDataDirectory = string.Format(RinexDirectory + "\\用户");
                    //写入用户Rinex2.10版观测数据
                    //WriteRinexObserveFileV210(UserDataDirectory, DataModel);
                    if (DataModel.SubModelList[0].IsChecked)
                    {
                        if (!Directory.Exists(UserDataDirectory))
                        {
                            Directory.CreateDirectory(UserDataDirectory);
                        }
                        WriteRinexObserveFileV210(UserDataDirectory, ESegmentType.UserSegment);
                    }
                    break;
                default:
                    break;
            }
            return true;
        }

        /// <summary>
        /// Rinex302 数据保存总入口
        /// </summary>
        /// <param name="RinexDirectory">文件保存路经</param>
        /// <param name="DataModel">模型节点类型</param>
        /// <returns></returns>
        public bool WriteRinex302File(string RinexDirectory, DataSaveFlagModel DataModel)
        {
            switch (DataModel.Name)
            {
                case "空间段":
                    string spaceDataDirectory = string.Format(RinexDirectory + "\\空间段");

                    //写入卫星精密星历SP3格式数据
                    if (DataModel.SubModelList[0].IsChecked)
                    {
                        if (!Directory.Exists(spaceDataDirectory))
                        {
                            Directory.CreateDirectory(spaceDataDirectory);
                        }
                        WriteRinexSP3File(spaceDataDirectory);
                    }
                    //写入卫星钟差Rinex格式数据
                    if (DataModel.SubModelList[1].IsChecked)
                    {
                        if (!Directory.Exists(spaceDataDirectory))
                        {
                            Directory.CreateDirectory(spaceDataDirectory);
                        }
                        WriteSatRinexClkFile(spaceDataDirectory);
                    }
                    break;
                case "地面控制段":
                    string StaDataDirectory = string.Format(RinexDirectory + "\\地面控制段");
                    //主控站存导航电文（2016.5.5）
                    if (DataModel.SubModelList[0].IsChecked)
                    {
                        if (!Directory.Exists(StaDataDirectory))
                        {
                            Directory.CreateDirectory(StaDataDirectory);
                        }
                        //待确定
                        WriteRinexNavMesgFile(StaDataDirectory, DataSaveType.Rinex3_02格式);
                    }
                    //监测站存入观测值
                    if (DataModel.SubModelList[1].IsChecked)
                    {
                        if (!Directory.Exists(StaDataDirectory))
                        {
                            Directory.CreateDirectory(StaDataDirectory);
                        }
                        WriteRinexObserveFileV302(StaDataDirectory, ESegmentType.GroudSegment);
                    }
                    //地面站存钟差数据
                    if (DataModel.SubModelList[2].IsChecked)
                    {
                        if (!Directory.Exists(StaDataDirectory))
                        {
                            Directory.CreateDirectory(StaDataDirectory);
                        }
                        WriteStationRinexClkFile(StaDataDirectory);
                    }

                    break;
                case "用户段":
                    string UserDataDirectory = string.Format(RinexDirectory + "\\用户段");
                    //写入用户Rinex2.10版观测数据
                    //WriteRinexObserveFileV210(UserDataDirectory, DataModel);
                    if (DataModel.SubModelList[0].IsChecked)
                    {
                        if (!Directory.Exists(UserDataDirectory))
                        {
                            Directory.CreateDirectory(UserDataDirectory);
                        }
                        WriteRinexObserveFileV302(UserDataDirectory, ESegmentType.UserSegment);
                    }
                    break;
                default:
                    break;
            }
            return true;
        }

        #region 写Rinex钟差数据
        /// <summary>
        ///  写卫星Rinex 钟数据文件
        /// </summary>
        /// <param name="ClkFilePath">卫星钟差文件保存路径</param>
        /// <param name="SatelliteList">卫星类集合</param>
        /// <param name="DataModel">数据保存模型节点</param>
        /// <returns></returns>
        public bool WriteSatRinexClkFile(string filePath)
        {
            foreach (var constellation in (Parent.SegmentColletion[0] as SpaceSegment).ConstellationList)
            {
                if (constellation.SatelliteCollection.Count > 0)
                {
                    //定义钟差文件名
                    string clkFilePath = filePath + "\\" + constellation.Name + "\\SAT_" + BDSimObject.GlobalStartTime.ToFileName() + ".clk";
                    Directory.CreateDirectory(filePath + "\\" + constellation.Name);
                    List<List<ClkSimData>> AllClkData = new List<List<ClkSimData>>();
                    RinexFileDataType.ClkHead clkHead = new RinexFileDataType.ClkHead(3.0, 0, 0);
                    //获取卫星系统类型
                    char systemType = SetSysType(constellation.ConstellationFeature.ConstellationType)[0];
                    clkHead.TypeNumber = 2;

                    //定义钟差头-卫星编号
                    clkHead.SatNumber = constellation.SatelliteCollection.Count;
                    for (int i = 0; i < clkHead.SatNumber; i++)
                    {
                        AllClkData.Add(constellation.SatelliteCollection[i].GenerateStepCLKErr(30));
                        clkHead.SatPRN[i] = constellation.SatelliteCollection[i].Id;
                        clkHead.SysType[i] = systemType;
                    }

                    //定义钟差头-文件生成时间
                    clkHead.CreateDate = new char[21];
                    DateTime NowTime = DateTime.Now;
                    string NowTimeString = NowTime.Year.ToString() + string.Format("{0:D2}", NowTime.Month) + string.Format("{0:D2}", NowTime.Day) +
                        " " + string.Format("{0:D2}", NowTime.Hour) + ":" + string.Format("{0:D2}", NowTime.Minute) + "UTC";
                    NowTimeString.CopyTo(0, clkHead.CreateDate, 0, NowTimeString.Length);
                    clkHead.LeapSeconds = ReadEOP.EOP_GetLeapSec(BDSimObject.GlobalStartTime) + 19;
                    //定义钟差头-钟差类型
                    clkHead.DataType[0] = ' ';
                    clkHead.DataType[1] = ' ';
                    clkHead.DataType[2] = ' ';
                    clkHead.DataType[3] = ' ';
                    clkHead.DataType[4] = 'A'; //地面站
                    clkHead.DataType[5] = 'R';
                    clkHead.DataType[6] = ' ';
                    clkHead.DataType[7] = ' ';
                    clkHead.DataType[8] = ' ';
                    clkHead.DataType[9] = ' ';
                    clkHead.DataType[10] = 'A';//卫星
                    clkHead.DataType[11] = 'S';
                    //写钟差头数据
                    if (!RinexFileDLL.WriteCLKHeader(clkFilePath.ToCharArray(), ref clkHead))
                    {
                        BDSimObject.DlgReportSimInfo(SimInfo.NewSimInfo(Parent.Name, "写" + constellation.Name + "星座卫星钟差文件头数据出错", OutputType.错误, BDSimObject.GlobalCurrentTime));
                    }
                    int clkCount = AllClkData[0].Count;
                    //RinexFileDataType.ClkDataAll allSatClk = new RinexFileDataType.ClkDataAll(clkCount);
                    //allSatClk.Hdr = clkHead;

                    //逐个时刻获取卫星钟差数据
                    for (int timeIndex = 0; timeIndex < clkCount; timeIndex++)
                    {
                        RinexFileDataType.ClkData clkData = new RinexFileDataType.ClkData(clkHead.SatNumber, 0);
                        clkData.Epoch = AllClkData[0][timeIndex].SimTime;
                        UTCTime systime = new UTCTime();

                        if (systemType == 'G')
                        {
                            TimeSpaceDll.UTC2GPST(clkData.Epoch.JD, out systime.JD);
                            systime.JD += 0.0001 / 86400.0;
                            TimeSpaceDll.CAL2UTC(out systime, 2);
                            systime.sec = (int)systime.sec;
                            clkData.Epoch = systime;
                        }

                        for (int satIndex = 0; satIndex < clkHead.SatNumber; satIndex++)
                        {
                            clkData.SatData[satIndex] = new RinexFileDataType.CLKDATA_Sat()
                            {
                                SatType = systemType,
                                flag = 1,
                                SatPrn = constellation.SatelliteCollection[satIndex].Id,
                                Clk = AllClkData[satIndex][timeIndex].ClkError,
                                RMS_Clk = 0.0
                            };
                        }
                        RinexFileDLL.WriteCLKREC(clkFilePath.ToCharArray(), ref clkData);
                    }
                    //关闭钟差文件
                    if (RinexFileDLL.FCloseWriteCLKREC() == 0)
                    {
                        BDSimObject.DlgReportSimInfo(SimInfo.NewSimInfo(Parent.Name, "写" + constellation.Name + "钟差数据关闭文件失败", OutputType.错误, BDSimObject.GlobalCurrentTime));
                    }
                }
            }
            return true;
        }

        /// <summary>
        ///  写卫星Rinex 钟数据文件
        /// </summary>
        /// <param name="ClkFilePath">卫星钟差文件保存路径</param>
        /// <param name="SatelliteList">卫星类集合</param>
        /// <param name="DataModel">数据保存模型节点</param>
        /// <returns></returns>
        public bool WriteStationRinexClkFile(string filePath)
        {

            foreach (var subGround in (Parent.SegmentColletion[2] as GroundSegment).SubGroundSegmentList)
            {
                List<StationBase> AllStation = new List<StationBase>();
                foreach (var stationList in subGround.GroundList)
                {
                    foreach (var station in stationList.StationList)
                    {
                        AllStation.Add(station);
                    }
                }
                if (AllStation.Count != 0)
                {
                    //定义钟差文件名
                    string clkFilePath = string.Format("{0}\\{1}\\{2}.clk", filePath, subGround.Name, BDSimObject.GlobalStartTime.ToFileName());
                    Directory.CreateDirectory(filePath + "\\" + subGround.Name);
                    List<List<ClkSimData>> AllClkData = new List<List<ClkSimData>>();
                    RinexFileDataType.ClkHead clkHead = new RinexFileDataType.ClkHead(3.0, 0, 0);
                    //获取卫星系统类型
                    char systemType = SetSysType(subGround.Type)[0];
                    clkHead.TypeNumber = 1;

                    //定义钟差头-卫星编号
                    clkHead.StationNumber = AllStation.Count;
                    for (int stationIndex = 0; stationIndex < clkHead.StationNumber; stationIndex++)
                    {

                        AllClkData.Add(AllStation[stationIndex].GenerateStepCLKErr(300));
                        //clkHead.SatPRN[i] = AllStation[i].Id;
                        clkHead.SysType[stationIndex] = systemType;
                        clkHead.Station_X[stationIndex] = AllStation[stationIndex].Pos_XYZ.X;
                        clkHead.Station_Y[stationIndex] = AllStation[stationIndex].Pos_XYZ.Y;
                        clkHead.Station_Z[stationIndex] = AllStation[stationIndex].Pos_XYZ.Z;
                        int nameLength = AllStation[stationIndex].Name.Length > 4 ? 4 : AllStation[stationIndex].Name.Length;
                        AllStation[stationIndex].Name.CopyTo(0, clkHead.StationName, stationIndex * 4, nameLength);
                    }

                    //定义钟差头-文件生成时间
                    clkHead.CreateDate = new char[21];
                    DateTime NowTime = DateTime.Now;
                    string NowTimeString = NowTime.Year.ToString() + string.Format("{0:D2}", NowTime.Month) + string.Format("{0:D2}", NowTime.Day) +
                        " " + string.Format("{0:D2}", NowTime.Hour) + ":" + string.Format("{0:D2}", NowTime.Minute) + "UTC";
                    NowTimeString.CopyTo(0, clkHead.CreateDate, 0, NowTimeString.Length);
                    clkHead.LeapSeconds = ReadEOP.EOP_GetLeapSec(BDSimObject.GlobalStartTime) + 19;
                    //定义钟差头-钟差类型
                    clkHead.DataType[0] = ' ';
                    clkHead.DataType[1] = ' ';
                    clkHead.DataType[2] = ' ';
                    clkHead.DataType[3] = ' ';
                    clkHead.DataType[4] = 'A'; //地面站
                    clkHead.DataType[5] = 'R';
                    clkHead.DataType[6] = ' ';
                    clkHead.DataType[7] = ' ';
                    clkHead.DataType[8] = ' ';
                    clkHead.DataType[9] = ' ';
                    clkHead.DataType[10] = 'A';//卫星
                    clkHead.DataType[11] = 'S';
                    //写钟差头数据
                    if (!RinexFileDLL.WriteCLKHeader(clkFilePath.ToCharArray(), ref clkHead))
                    {
                        BDSimObject.DlgReportSimInfo(SimInfo.NewSimInfo(Parent.Name, "写" + subGround.Name + "地面站钟差文件头数据出错", OutputType.错误, BDSimObject.GlobalCurrentTime));
                    }
                    int clkCount = AllClkData[0].Count;
                    //RinexFileDataType.ClkDataAll allSatClk = new RinexFileDataType.ClkDataAll(clkCount);
                    //allSatClk.Hdr = clkHead;

                    //逐个时刻获取地面站钟差数据
                    for (int timeIndex = 0; timeIndex < clkCount; timeIndex++)
                    {
                        RinexFileDataType.ClkData clkData = new RinexFileDataType.ClkData(0, clkHead.StationNumber);
                        clkData.Epoch = AllClkData[0][timeIndex].SimTime;
                        for (int stationIndex = 0; stationIndex < clkHead.StationNumber; stationIndex++)
                        {
                            clkData.StationData[stationIndex] = new RinexFileDataType.CLKDATA_Station()
                            {
                                StationName = new char[4],
                                flag = 1,
                                Clk = AllClkData[stationIndex][timeIndex].ClkError,
                                RMS_Clk = 0.0
                            };
                            int nameLength = AllStation[stationIndex].Name.Length > 4 ? 4 : AllStation[stationIndex].Name.Length;
                            AllStation[stationIndex].Name.CopyTo(0, clkData.StationData[stationIndex].StationName, 0, nameLength);
                        }
                        RinexFileDLL.WriteCLKREC(clkFilePath.ToCharArray(), ref clkData);
                    }
                    //关闭钟差文件
                    if (RinexFileDLL.FCloseWriteCLKREC() == 0)
                    {
                        BDSimObject.DlgReportSimInfo(SimInfo.NewSimInfo(Parent.Name, "写" + subGround.Name + "钟差数据关闭文件失败", OutputType.错误, BDSimObject.GlobalCurrentTime));
                    }
                }
            }
            return true;
        }

        private char[] SetSysType(EConstellationType constellation)
        {
            char[] systemType = new char[4];
            switch (constellation)
            {
                case EConstellationType.BD:
                    systemType = string.Format("CBD ").ToCharArray();
                    break;
                case EConstellationType.GPS:
                    systemType = string.Format("GGPS").ToCharArray();
                    break;
                case EConstellationType.GLONASS:
                    systemType = string.Format("RGLO").ToCharArray();
                    break;
                case EConstellationType.GALILEO:
                    systemType = string.Format("EGAL").ToCharArray();
                    break;
                default:
                    break;
            }
            return systemType;
        }
        #endregion

        #region //写SP3数据
        /// <summary>
        ///  写Rinex SP3轨道数据文件 
        /// </summary>
        /// <param name="SP3FilePath">卫星 SP3轨道数据文件保存路径</param>
        /// <param name="SatelliteList">卫星类集合</param>
        /// <param name="DataModel">数据保存模型节点</param>
        /// <returns></returns>
        public bool WriteRinexSP3File(string filePath)
        {
            foreach (var constellation in (Parent.SegmentColletion[0] as SpaceSegment).ConstellationList)
            {
                if (constellation.SatelliteCollection.Count > 0)
                {
                    //创建SP3数据文件名
                    string clkFilePath = filePath + "\\" + constellation.Name + "\\SAT_" + BDSimObject.GlobalStartTime.ToFileName() + ".sp3";
                    //创建文件保存路径
                    Directory.CreateDirectory(filePath + "\\" + constellation.Name);
                    //准备卫星轨道数据（15分钟采样间隔）
                    List<List<OrbitSimData>> AllOrbitData = new List<List<OrbitSimData>>();
                    List<List<ClkSimData>> AllClkData = new List<List<ClkSimData>>();
                    //获取导航系统类型参数
                    char[] sysFlag = SetSysType(constellation.ConstellationFeature.ConstellationType);
                    //初始化SP3数据体头部分
                    RinexFileDataType.SP3Head sp3Head = new RinexFileDataType.SP3Head()
                    {
                        DataType = new char[6] { 'O', 'R', 'B', 'I', 'T', '\0' },
                        Coordinate = new char[6] { ' ', 'I', 'T', 'R', 'F', '\0' },
                        OrbitType = new char[4] { 'F', 'I', 'T', '\0' },
                        SatPRN = new int[RinexFileDataType._MAX_SAT],
                        SatPrecision = new int[RinexFileDataType._MAX_SAT],
                        SatType = new char[RinexFileDataType._MAX_SAT]
                    };
                    sp3Head.Agent = new char[5] { sysFlag[1], sysFlag[2], sysFlag[3], 'T', 'H' };
                    //获取卫星轨道数据
                    for (int satIndex = 0; satIndex < constellation.SatelliteCollection.Count; satIndex++)
                    {
                        //获取轨道数据、钟差数据,SP3数据要求15分钟一组，此处采样间隔设置为900s
                        AllOrbitData.Add(constellation.SatelliteCollection[satIndex].GenerateStepOrbit(900));
                        AllClkData.Add(constellation.SatelliteCollection[satIndex].GenerateStepCLKErr(900));
                        //定义卫星PRN编号
                        sp3Head.SatPRN[satIndex] = constellation.SatelliteCollection[satIndex].Id;
                        sp3Head.SatType[satIndex] = constellationDic[constellation.ConstellationFeature.ConstellationType];
                    }

                    sp3Head.SP3Type = 'P';

                    sp3Head.SampPeriod = 900;
                    sp3Head.SatCount = constellation.SatelliteCollection.Count;
                    //根据系统类别赋值不同的周、周内秒（SP3头中数据）
                    UTCTime specifiedTime = new UTCTime();
                    UTC2TargetTime(BDSimObject.GlobalStartTime.Jd, constellation.ConstellationFeature.ConstellationType, ref sp3Head.InitWN, ref sp3Head.InitWeekSec, ref specifiedTime);
                    //sp3Head.InitWeekSec = Math.Ceiling(sp3Head.InitWeekSec);
                    //specifiedTime.Sec = Math.Ceiling(specifiedTime.Sec);
                    sp3Head.InitWeekSec = (int)sp3Head.InitWeekSec;
                    specifiedTime.Sec = (int)specifiedTime.Sec;
                    sp3Head.InitTime = specifiedTime;
                    sp3Head.InitIntJD = (int)(specifiedTime.Jd - 2400000.5);
                    sp3Head.InitDouJD = (specifiedTime.Jd - 2400000.5) % 1.0;
                    sp3Head.TotalEpoh = AllOrbitData[0].Count;
                    sp3Head.SysType = SetSysType(constellation.ConstellationFeature.ConstellationType)[0];
                    //写SP3数据体头部分到指定文件
                    RinexFileDLL.WriteSP3Header(clkFilePath.ToCharArray(), sp3Head);

                    for (int timeIndex = 0; timeIndex < sp3Head.TotalEpoh; timeIndex++)
                    {
                        //定义单组SP3数据
                        RinexFileDataType.SP3Data sp3Data = new RinexFileDataType.SP3Data() { Rec = new RinexFileDataType.SP3REC[RinexFileDataType._MAX_SAT] };
                        //获取数据时间
                        //sp3Data.Epoch = AllOrbitData[0][timeIndex].SatPV_ECI.Epoch;
                        UTC2TargetTime(AllOrbitData[0][timeIndex].SatPV_ECI.Epoch.Jd, constellation.ConstellationFeature.ConstellationType, ref sp3Data.Epoch);
                        //  sp3Data.Epoch.Sec = Math.Ceiling(sp3Data.Epoch.Sec);
                        sp3Data.Epoch.Sec = (int)sp3Data.Epoch.Sec;
                        for (int satIndex = 0; satIndex < constellation.SatelliteCollection.Count; satIndex++)
                        {
                            RinexFileDataType.SP3REC rec = new RinexFileDataType.SP3REC();
                            rec.Flag = 'P';
                            rec.PRN = sp3Head.SatPRN[satIndex];
                            //赋值x,y,z方向三个数据，数据类型：ECF，单位：km
                            NodePosVel tempECF = new NodePosVel();
                            TimeSpaceDll.ECI2ECF(AllOrbitData[satIndex][timeIndex].SatPV_ECI, 0, 0, out tempECF);
                            //  TimeSpaceDll.WGS2CGCS(tempECF, out tempECF);
                            rec.x = tempECF.x / 1000.0;
                            rec.y = tempECF.y / 1000.0;
                            rec.z = tempECF.z / 1000.0;
                            //钟改正，单位为10^-6s
                            rec.dt = AllClkData[satIndex][timeIndex].ClkError * 1e6;
                            sp3Data.Rec[satIndex] = rec;
                        }
                        RinexFileDLL.WriteSP3REC(clkFilePath.ToCharArray(), sp3Head, sp3Data, 0);
                    }
                    if (RinexFileDLL.FCloseWriteSP3REC() == 0)
                    {
                        BDSimObject.DlgReportSimInfo(SimInfo.NewSimInfo(Parent.Name, "写" + constellation.Name + "SP3数据关闭文件失败", OutputType.错误, BDSimObject.GlobalCurrentTime));
                    }
                }
            }

            return true;
        }


        /// <summary>
        /// UTC时转到指定时间系统的周，周内秒
        /// </summary>
        /// <param name="UTC_JD">UTC时儒略日</param>
        /// <param name="type">导航系统类型</param>
        /// <param name="wn">输出的周</param>
        /// <param name="sec">输出的周内秒</param>
        void UTC2TargetTime(double UTC_JD, EConstellationType type, ref int wn, ref double sec, ref UTCTime specifiedTime)
        {
            double navTimeJD = 0;
            //UTCTime specifiedTime = new UTCTime();
            switch (type)
            {
                case EConstellationType.BD:
                    TimeSpaceDll.UTC2BDT(UTC_JD, out navTimeJD);
                    navTimeJD += 0.0001 / 86400.0;
                    TimeSpaceDll.BDT_JD2WnSec(navTimeJD, out wn, out sec);
                    break;
                case EConstellationType.GPS:
                    TimeSpaceDll.UTC2GPST(UTC_JD, out navTimeJD);
                    navTimeJD += 0.0001 / 86400.0;
                    TimeSpaceDll.GPST_JD2WnSec(navTimeJD, out wn, out sec);
                    break;
                case EConstellationType.GLONASS:
                    TimeSpaceDll.UTC2GST(UTC_JD, out navTimeJD);
                    navTimeJD += 0.0001 / 86400.0;
                    TimeSpaceDll.GST_JD2WnSec(navTimeJD, out wn, out sec);
                    break;
                default:
                    break;
            }
            specifiedTime.JD = navTimeJD;
            TimeSpaceDll.CAL2UTC(out specifiedTime, 2);
        }
        void UTC2TargetTime(double UTC_JD, EConstellationType type, ref UTCTime specifiedTime)
        {
            int wn = 0;
            double sow = 0;
            UTC2TargetTime(UTC_JD, type, ref wn, ref sow, ref specifiedTime);
        }
        #endregion

        #region 写导航电文
        /// <summary>
        /// 写Rinex 导航数据文件
        /// </summary>
        /// <param name="filePath">文件路径</param>
        /// <param name="rinexType">Rinex版本类型</param>
        /// <returns></returns>
        public bool WriteRinexNavMesgFile(string filePath, DataSaveType rinexType)
        {
            //遍历所有子地面段
            foreach (var subGround in (Parent.SegmentColletion[2] as GroundSegment).SubGroundSegmentList)
            {
                //当写的Rinex版本为2.10，且星座类型为BD时，不执行写操作，其他情况均执行写导航电文
                if (!(rinexType == DataSaveType.Rinex2_10格式 && (subGround.Type == EConstellationType.BD || subGround.Type == EConstellationType.GALILEO)))
                {
                    //遍历子地面段中所有站集合
                    foreach (var stationList in subGround.GroundList)
                    {
                        //如果站集合是主控站，则进行导航电文写操作
                        if (stationList.Type == EStationType.MasterStation)
                        {
                            //遍历站集合中的所有主控站，写导航电文
                            for (int masterStationIndex = 0; masterStationIndex < stationList.StationList.Count; masterStationIndex++)
                            {
                                string navDataPath = filePath + "\\" + subGround.Name + "\\";
                                Directory.CreateDirectory(navDataPath);

                                NavMsgFit tempNavMsgFit = (stationList.StationList[masterStationIndex] as MasterStation).CNavMsgFit;
                                //定义当前写的导航电文的索引号
                                int navDataIndex = 0;
                                //定义当前写导航电文的天数
                                int dayIndex = 0;
                                //按天写导航电文
                                while ((stationList.StationList[masterStationIndex] as MasterStation).CNavMsgFit.Parent.SatEph16Dic.Count > 0 && navDataIndex < (stationList.StationList[masterStationIndex] as MasterStation).CNavMsgFit.Parent.SatEph16Dic.First().Value.Count)
                                {
                                    RinexFileDataType.NavMessageHead navHead = new RinexFileDataType.NavMessageHead()
                                    {
                                        PGM = new char[21],
                                        Agent = new char[21],
                                        CreateDate = new char[16],
                                        CreateDateType = new char[5],
                                        CommentLine = new char[61],
                                        TimeCorr = new char[5]
                                    };
                                    //获取当前一天首行星历数据的的时间
                                    UTCTime firstNavDataTime = (stationList.StationList[masterStationIndex] as MasterStation).CNavMsgFit.Parent.SatEph16Dic.First().Value[navDataIndex].t;
                                    string navDataFile = navDataPath + stationList.StationList[masterStationIndex].Name + "_" + firstNavDataTime.ToFileName() + '.' + firstNavDataTime.year.ToString().Substring(2) + 'n';

                                    char[] sysFlag = SetSysType(subGround.Type);
                                    //确定Rinex版本
                                    navHead.RnxVrsn = (rinexType == DataSaveType.Rinex2_10格式) ? 2.10 : 3.02;
                                    navHead.SysType = sysFlag[0];
                                    string.Format("BDSim").CopyTo(0, navHead.PGM, 0, 5);
                                    string.Format("SIRC").CopyTo(0, navHead.Agent, 0, 4);
                                    string.Format("UTC").CopyTo(0, navHead.CreateDateType, 0, 3);
                                    //赋值文件创建时间
                                    DateTime NowTime = DateTime.Now;
                                    string NowTimeString = NowTime.Year.ToString() + string.Format("{0:D2}", NowTime.Month) + string.Format("{0:D2}", NowTime.Day) +
                                        " " + string.Format("{0:D2}", NowTime.Hour) + ":" + string.Format("{0:D2}", NowTime.Minute);
                                    NowTimeString.CopyTo(0, navHead.CreateDate, 0, NowTimeString.Length);
                                    string.Format("UTC").CopyTo(0, navHead.CreateDateType, 0, 3);
                                    //赋值导航电文模式，0为简易模式，1为完整模式包含电离层等数据
                                    navHead.Model = 1;
                                    /*赋值电离层参数*/
                                    navHead.A0 = (stationList.StationList[masterStationIndex] as MasterStation).CNavMsgFit.Parent.IonoFitOutputMsgList[dayIndex].IonoFitOutput.EightIonoData.Alpha0;
                                    navHead.A1 = (stationList.StationList[masterStationIndex] as MasterStation).CNavMsgFit.Parent.IonoFitOutputMsgList[dayIndex].IonoFitOutput.EightIonoData.Alpha1;
                                    navHead.A2 = (stationList.StationList[masterStationIndex] as MasterStation).CNavMsgFit.Parent.IonoFitOutputMsgList[dayIndex].IonoFitOutput.EightIonoData.Alpha2;
                                    navHead.A3 = (stationList.StationList[masterStationIndex] as MasterStation).CNavMsgFit.Parent.IonoFitOutputMsgList[dayIndex].IonoFitOutput.EightIonoData.Alpha3;
                                    navHead.B0 = (stationList.StationList[masterStationIndex] as MasterStation).CNavMsgFit.Parent.IonoFitOutputMsgList[dayIndex].IonoFitOutput.EightIonoData.Beta0;
                                    navHead.B1 = (stationList.StationList[masterStationIndex] as MasterStation).CNavMsgFit.Parent.IonoFitOutputMsgList[dayIndex].IonoFitOutput.EightIonoData.Beta1;
                                    navHead.B2 = (stationList.StationList[masterStationIndex] as MasterStation).CNavMsgFit.Parent.IonoFitOutputMsgList[dayIndex].IonoFitOutput.EightIonoData.Beta2;
                                    navHead.B3 = (stationList.StationList[masterStationIndex] as MasterStation).CNavMsgFit.Parent.IonoFitOutputMsgList[dayIndex].IonoFitOutput.EightIonoData.Beta3;
                                    string.Format("BDUT").CopyTo(0, navHead.TimeCorr, 0, 4);
                                    /*获取跳秒值*/
                                    if (subGround.Type == EConstellationType.BD)
                                    {
                                        navHead.LeapSeconds = ReadEOP.EOP_GetLeapSec(firstNavDataTime) - 14;
                                    }
                                    if (subGround.Type == EConstellationType.GPS)
                                    {
                                        navHead.LeapSeconds = ReadEOP.EOP_GetLeapSec(firstNavDataTime);
                                    }

                                    navHead.UTCIden = 7;

                                    //按照2.10格式写头
                                    if (rinexType == DataSaveType.Rinex2_10格式)
                                    {
                                        RinexFileDLL.WriteNavHeader_V210(navDataFile.ToCharArray(), navHead);
                                    }
                                    else if (rinexType == DataSaveType.Rinex3_02格式)
                                    {
                                        RinexFileDLL.WriteNavHeader_V302(navDataFile.ToCharArray(), navHead);
                                    }
                                    for (; navDataIndex < (stationList.StationList[masterStationIndex] as MasterStation).CNavMsgFit.Parent.SatEph16Dic.First().Value.Count(); navDataIndex++)
                                    {
                                        int satPRN = 1;
                                        foreach (var navDataDicItem in (stationList.StationList[masterStationIndex] as MasterStation).CNavMsgFit.Parent.SatEph16Dic)
                                        {
                                            Ephemeris_16 ephemeris_16 = navDataDicItem.Value[navDataIndex];
                                            ephemeris_16.t.Jd = ephemeris_16.t.Jd + 0.0001 / 86400.0;
                                            double sys_jd;
                                            int sys_wn = ephemeris_16.WN;
                                            double sys_toe = ephemeris_16.toe;

                                            //由于星历的时间是UTC，输出RINEX文件时转换成对应的导航系统时输出
                                            //星历输出已改为导航系统时，但是由于时间转换的截断，导致秒不整，这里转换后处理成整秒
                                            switch (subGround.Type)
                                            {
                                                case EConstellationType.BD:
                                                    TimeSpaceDll.UTC2BDT(ephemeris_16.t.Jd, out sys_jd);
                                                    TimeSpaceDll.BDT_JD2WnSec(sys_jd, out sys_wn, out sys_toe);
                                                    ephemeris_16.t.Jd = sys_jd;
                                                    TimeSpaceDll.CAL2UTC(out ephemeris_16.t, 2);
                                                    break;
                                                case EConstellationType.GPS:
                                                    TimeSpaceDll.UTC2GPST(ephemeris_16.t.JD, out sys_jd);
                                                    TimeSpaceDll.GPST_JD2WnSec(sys_jd, out sys_wn, out sys_toe);
                                                    ephemeris_16.t.Jd = sys_jd;
                                                    TimeSpaceDll.CAL2UTC(out ephemeris_16.t, 2);
                                                    break;
                                                case EConstellationType.GALILEO:
                                                    TimeSpaceDll.UTC2GST(ephemeris_16.t.JD, out sys_jd);
                                                    TimeSpaceDll.GST_JD2WnSec(sys_jd, out sys_wn, out sys_toe);
                                                    ephemeris_16.t.Jd = sys_jd;
                                                    TimeSpaceDll.CAL2UTC(out ephemeris_16.t, 2);
                                                    break;
                                                default:
                                                    break;
                                            }
                                            ephemeris_16.t.sec = (int)ephemeris_16.t.sec;
                                            ephemeris_16.toe = (int)sys_toe;
                                            ephemeris_16.WN = sys_wn;
                                            ClkErrFitMsg clkErrFitMsg = (stationList.StationList[masterStationIndex] as MasterStation).CNavMsgFit.Parent.ClockErrDic[navDataDicItem.Key][navDataIndex];
                                            RinexFileDataType.NavMessage_Rinex navMessage = new RinexFileDataType.NavMessage_Rinex();
                                            navMessage.LoadData(ephemeris_16, clkErrFitMsg);
                                            navMessage.SysType = sysFlag[0];
                                            navMessage.PRN = satPRN;
                                            satPRN++;
                                            //写导航电文数据
                                            //按照2.10格式写数据体
                                            if (rinexType == DataSaveType.Rinex2_10格式)
                                            {
                                                RinexFileDLL.WriteNavREC_V210(navDataFile.ToCharArray(), navMessage);
                                            }
                                            //按照3.02格式写数据体
                                            else if (rinexType == DataSaveType.Rinex3_02格式)
                                            {
                                                RinexFileDLL.WriteNavREC_V302(navDataFile.ToCharArray(), navMessage);
                                            }
                                            if (satPRN > 30) break;//暂时添加，kj

                                        }
                                        //当下一组导航电文的小时小于当前组数据的小时，退出循环，写下一天的文件
                                        if (navDataIndex + 1 < (stationList.StationList[masterStationIndex] as MasterStation).CNavMsgFit.Parent.SatEph16Dic.First().Value.Count() && (stationList.StationList[masterStationIndex] as MasterStation).CNavMsgFit.Parent.SatEph16Dic.First().Value[navDataIndex + 1].t.hour < (stationList.StationList[masterStationIndex] as MasterStation).CNavMsgFit.Parent.SatEph16Dic.First().Value[navDataIndex].t.hour)
                                        {
                                            //天数跳到下一天，并重新写文件
                                            dayIndex++;
                                            //下一天写下一组导航电文
                                            navDataIndex++;
                                            //关闭文件后，重新写下一天的导航电文
                                            RinexFileDLL.FCloseWriteNavREC_V210();
                                            RinexFileDLL.FCloseWriteNavREC_V302();
                                            break;
                                        }
                                    }
                                }
                                //写完最后一天后关闭文件
                                RinexFileDLL.FCloseWriteNavREC_V210();
                                RinexFileDLL.FCloseWriteNavREC_V302();
                            }
                            //遍历到主控站并写完导航电文，就退出遍历站集合的循环
                            break;
                        }
                    }
                }
            }
            return true;
        }

        /// <summary>
        /// 写Rinex导航数据文件3.02版
        /// </summary>
        /// <param name="NavMsgFilePath">卫星 导航电文数据文件保存路径</param>
        /// <param name="SatelliteList">卫星类集合</param>
        /// <param name="DataModel">数据保存模型节点</param>
        /// <returns></returns>
        public bool WriteRinexNavMesgFileV302(string NavMsgFilePath, DataSaveFlagModel DataModel)
        {

            return true;
        }
        #endregion

        #region 写观测数据


        /// <summary>
        /// 写Rinex监测站观测数据文件 (只支持GPS和Glonass)
        /// </summary>
        /// <param name="filePath">监测站观测数据文件保存路径</param>
        /// <param name="MonitorStationList">监测站类集合</param>
        /// <param name="DataModel">数据保存模型节点</param>
        /// <returns></returns>
        public bool WriteRinexObserveFileV210(string filePath, ESegmentType segmentType)
        {
            //定义Rinex格式观测数据集合
            List<RinexFileDataType.ObsDataAll_v210> obsDataAllList = new List<RinexFileDataType.ObsDataAll_v210>();
            //对应保存观测数据的路径
            List<string> FileNameList = new List<string>();
            //从接收机或者监测站获取观测数据填充obsDataAllList
            switch (segmentType)
            {
                case ESegmentType.SpaceSegment:
                    break;
                case ESegmentType.GroudSegment:
                    foreach (var subGround in (this.Parent.SegmentColletion[2] as GroundSegment).SubGroundSegmentList)
                    {
                        foreach (var stationList in subGround.GroundList)
                        {
                            if (stationList.Type == EStationType.MonitorStation)
                            {
                                foreach (var station in stationList.StationList)
                                {
                                    if (((MonitorStation)station).MonitorReceivers[0].ALLObsSatsDataDic_ConType.Count>0)
                                    {
                                        RinexFileDataType.ObsDataAll_v210 obsDataAll = GetV210ObsDataAll((MonitorStation)station);
                                        obsDataAllList.Add(obsDataAll);
                                        FileNameList.Add(string.Format("{0}\\{1}\\{2}.{3}o", filePath, subGround.Name, station.Name, BDSimObject.GlobalStartTime.year.ToString().Substring(2)));
                                        Directory.CreateDirectory(string.Format("{0}\\{1}", filePath, subGround.Name));
                                    }
                                }
                                break;
                            }
                        }
                    }
                    break;
                case ESegmentType.UserSegment:
                    foreach (var user in (this.Parent.SegmentColletion[3] as UserSegment).UserModelList)
                    {
                        foreach (var receiver in user.RecCollection)
                        {
                            if (receiver.ALLObsSatsDataDic_ConType.Count > 0)
                            {
                                RinexFileDataType.ObsDataAll_v210 obsDataAll = GetV210ObsDataAll(receiver);
                                obsDataAllList.Add(obsDataAll);
                                FileNameList.Add(string.Format("{0}\\{1}\\{2}.{3}o", filePath, user.Name, receiver.Name, BDSimObject.GlobalStartTime.year.ToString().Substring(2)));
                                Directory.CreateDirectory(string.Format("{0}\\{1}", filePath, user.Name));
                            }
                        }
                    }
                    break;
                default:
                    break;
            }
            //开始写观测数据obsDataAllList
            for (int userIndex = 0; userIndex < obsDataAllList.Count; userIndex++)
            {
                RinexFileDataType.ObsDataAll_v210 ObsDataAll = obsDataAllList[userIndex];
                //写Rinex2.10格式观测数据头部分
                RinexFileDLL.WriteOBSHeader_V210(FileNameList[userIndex].ToCharArray(), ref ObsDataAll.Hdr);
                for (int timeIndex = 0; timeIndex < ObsDataAll.ObsData.Length; timeIndex++)
                {
                    //写Rinex2.10格式观测数据体部分
                    RinexFileDLL.WriteOBSREC_V210(FileNameList[userIndex].ToCharArray(), ref ObsDataAll.ObsData[timeIndex], ref ObsDataAll.Hdr);
                }
                int flag = RinexFileDLL.FCloseWriteOBSREC_V210();
            }
            return true;
        }

        /// <summary>
        /// 写Rinex 监测站观测数据文件v3.02版
        /// </summary>
        /// <param name="RinexObserveFilePath">监测站观测数据文件保存路径</param>
        /// <param name="MonitorStationList">监测站类集合</param>
        /// <param name="DataModel">数据保存模型节点</param>
        /// <returns></returns>
        public bool WriteRinexObserveFileV302(string filePath, ESegmentType segmentType)
        {
            //定义Rinex格式观测数据集合
            List<RinexFileDataType.ObsDataAll_v302> obsDataAllList = new List<RinexFileDataType.ObsDataAll_v302>();
            //对应保存观测数据的路径
            List<string> FileNameList = new List<string>();
            //从接收机或者监测站获取观测数据填充obsDataAllList
            switch (segmentType)
            {
                case ESegmentType.SpaceSegment:
                    break;
                case ESegmentType.GroudSegment:
                    foreach (var subGround in (this.Parent.SegmentColletion[2] as GroundSegment).SubGroundSegmentList)
                    {
                        foreach (var stationList in subGround.GroundList)
                        {
                            if (stationList.Type == EStationType.MonitorStation)
                            {
                                foreach (var station in stationList.StationList)
                                {
                                    RinexFileDataType.ObsDataAll_v302 obsDataAll = GetV302ObsDataAll((MonitorStation)station);
                                    obsDataAllList.Add(obsDataAll);
                                    FileNameList.Add(string.Format("{0}\\{1}\\{2}.{3}o", filePath, subGround.Name, station.Name, obsDataAll.Hdr.FrstObsvTime.Year.ToString().Substring(2)));
                                    Directory.CreateDirectory(string.Format("{0}\\{1}", filePath, subGround.Name));
                                }
                                break;
                            }

                        }
                    }
                    break;
                case ESegmentType.UserSegment:
                    foreach (var user in (this.Parent.SegmentColletion[3] as UserSegment).UserModelList)
                    {
                        foreach (var receiver in user.RecCollection)
                        {
                            RinexFileDataType.ObsDataAll_v302 obsDataAll = GetV302ObsDataAll(receiver);
                            obsDataAllList.Add(obsDataAll);
                            FileNameList.Add(string.Format("{0}\\{1}\\{2}.{03}o", filePath, user.Name, receiver.Name, obsDataAll.Hdr.FrstObsvTime.Year.ToString().Substring(2)));
                            Directory.CreateDirectory(string.Format("{0}\\{1}", filePath, user.Name));
                        }
                    }
                    break;
                default:
                    break;
            }
            //开始写观测数据obsDataAllList
            for (int userIndex = 0; userIndex < obsDataAllList.Count; userIndex++)
            {
                RinexFileDataType.ObsDataAll_v302 ObsDataAll = obsDataAllList[userIndex];
                int flag1 = RinexFileDLL.WriteOBSHeader_V302(FileNameList[userIndex].ToCharArray(), ref ObsDataAll.Hdr);
                for (int timeIndex = 0; timeIndex < ObsDataAll.ObsData.Length; timeIndex++)
                {
                    RinexFileDLL.WriteOBSREC_V302(FileNameList[userIndex].ToCharArray(), ref ObsDataAll.ObsData[timeIndex], ref ObsDataAll.Hdr);
                }
                int flag = RinexFileDLL.FCloseWriteOBSREC_V302();
            }
            return true;
        }

        /// <summary>
        /// 生成观测数据2.10格式数据体
        /// </summary>
        /// <param name="obsObject">监测站或用户接收机</param>
        /// <returns></returns>
        private RinexFileDataType.ObsDataAll_v210 GetV210ObsDataAll(BDSimObject obsObject)
        {
            RinexFileDataType.ObsDataAll_v210 obsDataAll = new RinexFileDataType.ObsDataAll_v210();// { ObsData = new RinexFileDataType.ObserveData[3000] };
            List<List<List<ObsReceiverOutput>>> allObsObsReceiverOutput = new List<List<List<ObsReceiverOutput>>>();
            char satFlag = '\0';
            if (obsObject is CReceiver)
            {
                allObsObsReceiverOutput = (obsObject as CReceiver).AllObsSatsDataList;
                obsDataAll.Hdr = GetObsHeadFromReceiver(obsObject as CReceiver);
                satFlag = receiverDic[(obsObject as CReceiver).RecType];
            }
            if (obsObject is MonitorStation)
            {
                List<Dictionary<string, List<ObsReceiverOutput>>> AllSatsObsDataDic = new List<Dictionary<string, List<ObsReceiverOutput>>>();
                foreach (var item in (obsObject as MonitorStation).MonitorReceivers[0].AllSatsObsDataDic)
                {
                    allObsObsReceiverOutput.Add(item.Values.ToList());
                }
                obsDataAll.Hdr = GetObsHeadFromMonitor(obsObject as MonitorStation);
                satFlag = constellationDic[(obsObject as MonitorStation).Parent.Parent.Type];
            }

            obsDataAll.Hdr.Versn = 2.10;
            obsDataAll.Hdr.ObsvTypeCount = allObsObsReceiverOutput[0][0].Count * 3;
            obsDataAll.ObsData = new RinexFileDataType.ObserveData[allObsObsReceiverOutput.Count];

            for (int timeIndex = 0; timeIndex < allObsObsReceiverOutput.Count; timeIndex++)
            {
                RinexFileDataType.ObserveData observeData = new RinexFileDataType.ObserveData() { Sta2SatObsData = new RinexFileDataType.SatOBS[100] };
                List<List<ObsReceiverOutput>> AllSatSingleTimeObs = allObsObsReceiverOutput[timeIndex];
                observeData.hdr = new RinexFileDataType.GMORECHDR()
                {
                    SatFlag = new char[100],
                    Prn = new int[100],
                    Epoch = AllSatSingleTimeObs[0][0].CurTime,
                    SatCount = (uint)AllSatSingleTimeObs.Count()
                };
                for (int satIndex = 0; satIndex < AllSatSingleTimeObs.Count; satIndex++)
                {
                    List<ObsReceiverOutput> satSingleTimeObs = AllSatSingleTimeObs[satIndex];
                    int freCount = satSingleTimeObs.Count;
                    observeData.hdr.Prn[satIndex] = satIndex + 1;
                    observeData.hdr.SatFlag[satIndex] = satFlag;
                    observeData.Sta2SatObsData[satIndex].ObsValue = new double[30];
                    for (int freIndex = 0; freIndex < freCount; freIndex++)
                    {
                        observeData.Sta2SatObsData[satIndex].ObsValue[freIndex * freCount] = satSingleTimeObs[freIndex].SatObs.A_Pseudo_writein;
                        observeData.Sta2SatObsData[satIndex].ObsValue[freIndex * freCount + 1] = satSingleTimeObs[freIndex].SatObs.A_Carri_writein;
                        observeData.Sta2SatObsData[satIndex].ObsValue[freIndex * freCount + 2] = satSingleTimeObs[freIndex].SatObs.DoplShift;
                    }
                }
                obsDataAll.ObsData[timeIndex] = observeData;
            }
            return obsDataAll;
        }


        /// <summary>
        /// 生成观测数据3.02格式数据体
        /// </summary>
        /// <param name="obsObject">监测站或用户接收机</param>
        /// <returns></returns>
        private RinexFileDataType.ObsDataAll_v302 GetV302ObsDataAll(BDSimObject obsObject)
        {

            RinexFileDataType.ObsDataAll_v302 obsDataAll = new RinexFileDataType.ObsDataAll_v302();// { ObsData = new RinexFileDataType.ObserveData_v302[3000] };
            List<Dictionary<EConstellationType, Dictionary<string, List<ObsReceiverOutput>>>> ALLObsSatsDataDic_ConType = new List<Dictionary<EConstellationType, Dictionary<string, List<ObsReceiverOutput>>>>();
   
            char satFlag = '\0';
            Dictionary<ERecType, List<EFrePoint>> RecType_Fre =new Dictionary<ERecType, List<EFrePoint>>();
            //接收机目标进行赋值
            if (obsObject is CReceiver)
            {
               ALLObsSatsDataDic_ConType = (obsObject as CReceiver).ALLObsSatsDataDic_ConType;
                obsDataAll.Hdr = GetObsHeadFromReceiver(obsObject as CReceiver);
                RecType_Fre = (obsObject as CReceiver).RecType_Fre;
            }
            //监测站目标赋值
            if (obsObject is MonitorStation)
            {
                ALLObsSatsDataDic_ConType = (obsObject as MonitorStation).MonitorReceivers[0].ALLObsSatsDataDic_ConType;
                obsDataAll.Hdr = GetObsHeadFromMonitor(obsObject as MonitorStation);
                RecType_Fre = (obsObject as MonitorStation).MonitorReceivers[0].RecType_Fre;
            }
            obsDataAll.Hdr.Versn = 3.02;
            int sysnum = 0;
            foreach (var sys in RecType_Fre.Keys)
            {                
                obsDataAll.Hdr.obsvdescrip_V302[sysnum].SatSysCode = receiverDic[sys];
                obsDataAll.Hdr.obsvdescrip_V302[sysnum].ObsvTypCount = RecType_Fre[sys].Count * 2;
                obsDataAll.Hdr.obsvdescrip_V302[sysnum].ObsvDescrip = new char[20 * 4];               
                string strObsType = "";
                switch (sys)
                {
                    case ERecType.BD:
                        foreach (var fre in RecType_Fre[sys])
                        {
                            if (fre == EFrePoint.BD_B1)
                            {
                                strObsType += "C2I\0L2I\0";
                            }
                            if (fre == EFrePoint.BD_B2)
                            {
                                strObsType += "C7I\0L7I\0";
                            }
                            if (fre == EFrePoint.BD_B3)
                            {
                                strObsType += "C6I\0L6I\0";
                            }
                        }                       
                      //  strObsType = "C2I\0L2I\0C7I\0L7I\0C6I\0L6I";//
                        break;
                    case ERecType.GPS:
                        foreach (var fre in RecType_Fre[sys])
                        {
                            if (fre == EFrePoint.GPS_L1)
                            {
                                strObsType += "C1C\0L1C\0";
                            }
                            if (fre == EFrePoint.GPS_L2)
                            {
                                strObsType += "C2P\0L2P\0";
                            }
                            if (fre == EFrePoint.GPS_L5)
                            {
                                strObsType += "C5I\0L5I\0";
                            }
                        }
                        //strObsType = "C1C\0L1C\0C2P\0L2P\0C5I\0L5I";//
                        break;
                    case ERecType.GLONASS:
                        foreach (var fre in RecType_Fre[sys])
                        {
                            if (fre == EFrePoint.GLONASS_L1)
                            {
                                strObsType += "C1C\0L1C\0";
                            }
                            if (fre == EFrePoint.GLONASS_L1)
                            {
                                strObsType += "C2C\0L2C\0";
                            }
                        }
                        // strObsType = "C1C\0L1C\0C2C\0L2C";
                        break;
                    case ERecType.GALILEO:
                        foreach (var fre in RecType_Fre[sys])
                        {
                            if (fre == EFrePoint.GALILEO_E1)
                            {
                                strObsType += "C1A\0L1A\0";
                            }
                            if (fre == EFrePoint.GALILEO_E5a)
                            {
                                strObsType += "C5I\0L5I\0";
                            }
                            if (fre == EFrePoint.GALILEO_E5b)
                            {
                                strObsType += "C7I\0L7I\0";
                            }
                        }
                        // strObsType = "C1A\0L1A\0C5I\0L5I\0C7I\0L7I";
                        break;
                    default:
                        break;                       
                }               
                System.Array.Copy(strObsType.ToCharArray(), obsDataAll.Hdr.obsvdescrip_V302[sysnum].ObsvDescrip, strObsType.ToCharArray().Length);
                sysnum++;
            }


            obsDataAll.ObsData = new RinexFileDataType.ObserveData_v302[ALLObsSatsDataDic_ConType.Count];

            for (int timeIndex = 0; timeIndex < ALLObsSatsDataDic_ConType.Count; timeIndex++)
            {
                RinexFileDataType.ObserveData_v302 recObsData = new RinexFileDataType.ObserveData_v302() { Sta2SatObsData = new RinexFileDataType.SatOBS_v302[100], SatID = new int[RinexFileDataType._MAX_SAT_VISIBLE], SatSysCode = new char[RinexFileDataType._MAX_SAT_VISIBLE] };

                recObsData.hdr = new RinexFileDataType.GMORECHDR()
                {
                    SatFlag = new char[RinexFileDataType._MAX_SAT_VISIBLE],
                    Prn = new int[RinexFileDataType._MAX_SAT_VISIBLE],
                   
                };
                if (obsDataAll.Hdr.TimeSystem[0] == 'B')
                {
                    double BDJD;
                    TimeSpaceDll.UTC2BDT(recObsData.hdr.Epoch.Jd, out BDJD);
                    recObsData.hdr.Epoch.Jd = BDJD + 0.0001 / 86400.0;
                    TimeSpaceDll.CAL2UTC(out recObsData.hdr.Epoch, 2);
                    recObsData.hdr.Epoch.sec = (int)recObsData.hdr.Epoch.sec;
                }
                else if (obsDataAll.Hdr.TimeSystem[0] == 'G')
                {
                    double GPSJD;
                    TimeSpaceDll.UTC2GPST(recObsData.hdr.Epoch.Jd, out GPSJD);
                    recObsData.hdr.Epoch.Jd = GPSJD + 0.0001 / 86400.0;
                    TimeSpaceDll.CAL2UTC(out recObsData.hdr.Epoch, 2);
                    recObsData.hdr.Epoch.sec = (int)recObsData.hdr.Epoch.sec;
                }

                int satIndex = 0;
                foreach (var con in ALLObsSatsDataDic_ConType[timeIndex].Keys)
                {
                    satFlag = constellationDic[con];
                    foreach (var sat in ALLObsSatsDataDic_ConType[timeIndex][con].Keys)
                    {                        
                        List<ObsReceiverOutput> satSingleTimeObs = ALLObsSatsDataDic_ConType[timeIndex][con][sat];
                        recObsData.hdr.Epoch = satSingleTimeObs[0].CurTime;
                        int freCount = satSingleTimeObs.Count;
                        recObsData.SatID[satIndex] = satSingleTimeObs[0].SatID;
                        recObsData.SatSysCode[satIndex] = satFlag;
                        recObsData.Sta2SatObsData[satIndex].ObsValue = new double[RinexFileDataType._MAX_CNT_OBS_TYPE_V302];
                        recObsData.Sta2SatObsData[satIndex].LosingLockIdentifier = new uint[RinexFileDataType._MAX_CNT_OBS_TYPE_V302];
                        recObsData.Sta2SatObsData[satIndex].SignalStrength = new uint[RinexFileDataType._MAX_CNT_OBS_TYPE_V302];
                        for (int freIndex = 0; freIndex < freCount; freIndex++)
                        {
                            recObsData.Sta2SatObsData[satIndex].ObsValue[2 * freIndex] = satSingleTimeObs[freIndex].SatObs.A_Pseudo_writein;
                            recObsData.Sta2SatObsData[satIndex].ObsValue[2 * freIndex + 1] = satSingleTimeObs[freIndex].SatObs.A_Carri_writein;
                        }
                        satIndex++;
                    }
                }
                recObsData.hdr.SatCount = (uint)satIndex;

                obsDataAll.ObsData[timeIndex] = recObsData;
            }
            ALLObsSatsDataDic_ConType.Clear();
            return obsDataAll;
        }

        /// <summary>
        /// 把接收机相关数据赋值给观测数据头，并返回一个观测数据头对象
        /// </summary>
        /// <param name="rec"></param>
        /// <returns></returns>
        RinexFileDataType.ObserveHead GetObsHeadFromReceiver(CReceiver rec)
        {
            RinexFileDataType.ObserveHead head = new RinexFileDataType.ObserveHead();
            //char satSysType = receiverDic[rec.RecType];
            char satSysType='C';
            if (rec.RecType_Fre.Keys.Count > 1)
            {
                satSysType = 'M';
            }
            else
            {
                foreach (ERecType recType in rec.RecType_Fre.Keys)
                {
                    satSysType = receiverDic[recType];
                }               
            }
            
            RinexFileDataType.InitObserveFileHead_V210(ref head, satSysType);
            //赋值文件创建时间
            DateTime NowTime = DateTime.Now;
            string NowTimeString = NowTime.Year.ToString() + string.Format("{0:D2}", NowTime.Month) + string.Format("{0:D2}", NowTime.Day) +
                " " + string.Format("{0:D2}", NowTime.Hour) + ":" + string.Format("{0:D2}", NowTime.Minute) + "UTC";
            NowTimeString.CopyTo(0, head.CreateDate, 0, NowTimeString.Length);
            //赋值测站名称
            string markName = string.Format(rec.Name);
            markName.CopyTo(0, head.MarkName, 0, markName.Length);
            //赋值卫星系统类型
            head.SatSystemType[0] = satSysType;
            //如果是静态用户，则赋值用户位置信息，否则不赋值
            if (rec.Parent.Type == EUserType.StaticUser)
            {
                head.ApproxPos.x = rec.Parent.PosVelXYZ.x;
                head.ApproxPos.y = rec.Parent.PosVelXYZ.y;
                head.ApproxPos.z = rec.Parent.PosVelXYZ.z;
            }
            rec.RecType.ToString().CopyTo(0, head.RecvType, 0, rec.RecType.ToString().Length);
            head.AntDelta_XYZ.x = rec.RecInstallM.Alfa;
            head.AntDelta_XYZ.y = rec.RecInstallM.Beta;
            head.AntDelta_XYZ.z = rec.RecInstallM.Gama;
            head.Intval = BDSimObject.GlobalStepSize;

            EConstellationType temp = rec.ALLObsSatsDataDic_ConType[0].Keys.ToList()[0];
            string tempsat = rec.ALLObsSatsDataDic_ConType[0][temp].Keys.ToList()[0];
            head.FrstObsvTime = rec.ALLObsSatsDataDic_ConType[0][temp][tempsat][0].CurTime;

            temp = rec.ALLObsSatsDataDic_ConType.Last().Keys.ToList()[0];
            tempsat = rec.ALLObsSatsDataDic_ConType.Last()[temp].Keys.ToList()[0];
            head.LastObsvTime = rec.ALLObsSatsDataDic_ConType.Last()[temp][tempsat][0].CurTime;

            string.Format("UTC").CopyTo(0, head.TimeSystem, 0, 3);
            head.LeapSec = ReadEOP.EOP_GetLeapSec(BDSimObject.GlobalStartTime) + 19;
            //head.ClockCorrectFlag = Convert.ToInt32(rec.ObsErrCtrlFlag.IsSatClk);
            switch (rec.SatclkModelPVT)
            {
                case ESatClkModelType.多项式模型:
                    head.ClockCorrectFlag = 1;
                    break;
                case ESatClkModelType.不考虑:
                    head.ClockCorrectFlag = 0;
                    break;
                default:
                    break;
            }
            return head;
        }

        /// <summary>
        /// 把监测站相关数据赋值给观测数据头，并返回一个观测数据头对象
        /// </summary>
        /// <param name="rec"></param>
        /// <returns></returns>
        RinexFileDataType.ObserveHead GetObsHeadFromMonitor(MonitorStation monitor)
        {
            RinexFileDataType.ObserveHead head = new RinexFileDataType.ObserveHead();
            char satSysType = 'C';
            if (monitor.MonitorReceivers[0].RecType_Fre.Keys.Count > 1)
            {
                satSysType = 'M';
            }
            else
            {
                foreach (ERecType recType in monitor.MonitorReceivers[0].RecType_Fre.Keys)
                {
                    satSysType = receiverDic[recType];
                }
            }

            RinexFileDataType.InitObserveFileHead_V210(ref head, satSysType);
            //赋值文件创建时间
            DateTime NowTime = DateTime.Now;
            string NowTimeString = NowTime.Year.ToString() + string.Format("{0:D2}", NowTime.Month) + string.Format("{0:D2}", NowTime.Day) +
                " " + string.Format("{0:D2}", NowTime.Hour) + ":" + string.Format("{0:D2}", NowTime.Minute) + "UTC";
            NowTimeString.CopyTo(0, head.CreateDate, 0, NowTimeString.Length);
            //赋值测站名称
            string markName = string.Format(monitor.Name);
            markName.CopyTo(0, head.MarkName, 0, markName.Length);
            //赋值卫星系统类型
            head.SatSystemType[0] = satSysType;
            //则赋值用户位置信息

            head.ApproxPos.x = monitor.Pos_XYZ.X;
            head.ApproxPos.y = monitor.Pos_XYZ.Y;
            head.ApproxPos.z = monitor.Pos_XYZ.Z;

             head.Intval = BDSimObject.GlobalStepSize;

            EConstellationType temp = monitor.MonitorReceivers[0].ALLObsSatsDataDic_ConType[0].Keys.ToList()[0];
            string tempsat = monitor.MonitorReceivers[0].ALLObsSatsDataDic_ConType[0][temp].Keys.ToList()[0];
            head.FrstObsvTime = monitor.MonitorReceivers[0].ALLObsSatsDataDic_ConType[0][temp][tempsat][0].CurTime;

            temp = monitor.MonitorReceivers[0].ALLObsSatsDataDic_ConType.Last().Keys.ToList()[0];
            tempsat = monitor.MonitorReceivers[0].ALLObsSatsDataDic_ConType.Last()[temp].Keys.ToList()[0];
            head.LastObsvTime = monitor.MonitorReceivers[0].ALLObsSatsDataDic_ConType.Last()[temp][tempsat][0].CurTime;
            string.Format("UTC").CopyTo(0, head.TimeSystem, 0, 3);
            head.LeapSec = ReadEOP.EOP_GetLeapSec(BDSimObject.GlobalStartTime) + 19;

            return head;
        }


        #endregion

        /// <summary>
        /// 保存自定义格式数据
        /// </summary>
        /// <param name="TextDirectory"></param>
        /// <param name="DataModel"></param>
        /// <returns></returns>
        public bool SaveTextData(string TextDirectory, DataSaveFlagModel DataModel)
        {
            switch (DataModel.Name)
            {
                case "空间段":
                    string spaceDataDirectory = string.Format(TextDirectory + "\\空间段\\");
                    //写入卫星轨道数据
                    if (DataModel.SubModelList[0].IsChecked)
                    {
                        SaveSatOrbitTextData(spaceDataDirectory);
                    }
                    //写入卫星钟差数据
                    if (DataModel.SubModelList[1].IsChecked)
                    {
                        SaveSatClkTextData(spaceDataDirectory);
                    }
                    break;
                case "地面控制段":
                    string StaDataDirectory = string.Format(TextDirectory + "\\地面控制段\\");
                    SaveGroundTextData(StaDataDirectory, DataModel);
                    break;
                case "用户段":
                    string UserDataDirectory = string.Format(TextDirectory + "\\用户段\\");
                    SaveUserTextData(UserDataDirectory, DataModel);
                    break;
                default:
                    break;
            }


            return true;
        }

        /// <summary>
        /// 自定义保存卫星轨道数据
        /// </summary>
        /// <param name="TextDirectory"></param>
        void SaveSatOrbitTextData(string TextDirectory)
        {
            SpaceSegment temp = Parent.SegmentColletion[0] as SpaceSegment;
            foreach (var item in temp.ConstellationList)
            {
                TextDirectory = TextDirectory + item.Name;
                string OrbitECIFileName = TextDirectory + "\\轨道数据\\ECI\\";
                string OrbitECFFileName = TextDirectory + "\\轨道数据\\ECF\\";
                if (!Directory.Exists(OrbitECIFileName))
                {
                    Directory.CreateDirectory(OrbitECIFileName);
                }
                if (!Directory.Exists(OrbitECFFileName))
                {
                    Directory.CreateDirectory(OrbitECFFileName);
                }
                foreach (var sat in item.SatelliteCollection)
                {
                    string OrbitECISat = OrbitECIFileName + sat.Name + ".txt";
                    string OrbitECFSat = OrbitECFFileName + sat.Name + ".txt";
                    OrbitDataWriter orbitWriterECI = new OrbitDataWriter();
                    OrbitDataWriter orbitWriterECF = new OrbitDataWriter();
                    orbitWriterECI.InitSatWriteFileCfg(OrbitECISat, sat.Name, CoordinateSystem.J2000);
                    orbitWriterECF.InitSatWriteFileCfg(OrbitECFSat, sat.Name, CoordinateSystem.CGCS2000);
                    List<OrbitSimData> InterpolationOrbitData = sat.GenerateStepOrbit((int)(BDSimObject.GlobalStepSize));

                    //  写插值后的ECI、ECF数据
                    foreach (var SatOrbitItem in InterpolationOrbitData)
                    {
                        orbitWriterECI.WriteFile(SatOrbitItem.SatPV_ECI);

                        NodePosVel temp_ECF = new NodePosVel();
                        TimeSpaceDll.ECI2ECF(SatOrbitItem.SatPV_ECI, 0, 0, out temp_ECF);
                        TimeSpaceDll.WGS2CGCS(temp_ECF, out temp_ECF);
                        orbitWriterECF.WriteFile(temp_ECF);
                        //orbitWriterECF.WriteFile(SatOrbitItem.SatPV_ECF);
                    }
                }
            }
        }

        /// <summary>
        /// 自定义保存卫星钟差数据
        /// </summary>
        /// <param name="TextDirectory"></param>
        void SaveSatClkTextData(string TextDirectory)
        {
            SpaceSegment temp = Parent.SegmentColletion[0] as SpaceSegment;
            foreach (var item in temp.ConstellationList)
            {
                TextDirectory = TextDirectory + item.Name;
                string ClkFileName = TextDirectory + "\\钟差数据\\";
                if (!Directory.Exists(ClkFileName))
                {
                    Directory.CreateDirectory(ClkFileName);
                }

                foreach (var sat in item.SatelliteCollection)
                {
                    string ClkSat = ClkFileName + sat.Name + ".txt";
                    ClockDataWriter clkWriter = new ClockDataWriter();
                    clkWriter.InitClockDataFile(ClkSat, sat.Name, "北斗开放实验室");
                    List<ClkSimData> InterpolationClockData = sat.GenerateStepCLKErr((int)(BDSimObject.GlobalStepSize));

                    //  写插值后的钟差数据
                    foreach (var ClkItem in InterpolationClockData)
                    {
                        clkWriter.WriteFile(ClkItem.SimTime, ClkItem.ClkError);
                    }
                }
            }
        }
        

        /// <summary>
        /// 自定义格式保存地面站数据
        /// </summary>
        /// <param name="StaDataDirectory"></param>
        /// <param name="DataModel"></param>
        void SaveGroundTextData(string StaDataDirectory, DataSaveFlagModel DataModel)
        {
            foreach (var item in (Parent.SegmentColletion[2] as GroundSegment).SubGroundSegmentList)
            {
                foreach (var staitem in item.GroundList)
                {
                    foreach (var station in staitem.StationList)
                    {
                        string StationClkType;
                        switch (station.Type)
                        {
                            case EStationType.MasterStation:
                                StationClkType = "主控站";
                                if (DataModel.SubModelList[2].IsChecked)
                                {
                                    SaveStationClkData(StaDataDirectory, StationClkType, station.Name, station.GenerateStepCLKErr());
                                }
                                if (DataModel.SubModelList[0].IsChecked)
                                {
                                    SaveEphData(StaDataDirectory, ((MasterStation)station).SatEph16Dic, item.Type);
                                    SaveClockFitData(StaDataDirectory, ((MasterStation)station).ClockErrDic);
                                    SaveIonFitData(StaDataDirectory, ((MasterStation)station).IonoFitOutputMsgList);
                                }
                                break;
                            case EStationType.InjectionStation:
                                StationClkType = "注入站";
                                if (DataModel.SubModelList[2].IsChecked)
                                {
                                    SaveStationClkData(StaDataDirectory, StationClkType, station.Name, station.GenerateStepCLKErr());
                                }
                                break;
                            case EStationType.MonitorStation:
                                StationClkType = "监测站";
                                if (DataModel.SubModelList[2].IsChecked)
                                {
                                    SaveStationClkData(StaDataDirectory, StationClkType, station.Name, station.GenerateStepCLKErr());
                                }
                                if (DataModel.SubModelList[1].IsChecked)
                                {
                                    SaveObsTextData(StaDataDirectory, ESegmentType.GroudSegment);
                                }
                                break;
                            default:
                                break;
                        }
                    }
                }
            }
        }

        /// <summary>
        ///保存地面站钟差数据
        /// </summary>
        /// <param name="directotyname"></param>
        /// <param name="InterSatClkErrList"></param>
        public void SaveStationClkData(string directotyname, string StationType, string StationName, List<ClkSimData> InterSatClkErrList)
        {
            //创建保存数据文件路径及文件
            directotyname = directotyname + "\\" + StationType + "\\钟差数据\\";
            if (!Directory.Exists(directotyname))
            {
                Directory.CreateDirectory(directotyname);
            }
            directotyname += StationName + "-钟差数据.txt";

            ClockDataWriter clkWriter = new ClockDataWriter();
            clkWriter.InitClockDataFile(directotyname, StationName, "北斗开放实验室");

            //  写插值后的钟差数据
            foreach (var ClkItem in InterSatClkErrList)
            {
                clkWriter.WriteFile(ClkItem.SimTime, ClkItem.ClkError);
            }
        }

        /// <summary>
        /// 星历数据存储
        /// </summary>
        public void SaveEphData(string directotyname, Dictionary<string, List<Ephemeris_16>> SatEph16Dic, EConstellationType satType)
        {
            //创建保存数据文件路径及文件
            directotyname = directotyname + "\\主控站\\导航电文参数\\星历数据\\";
            if (!Directory.Exists(directotyname))
            {
                Directory.CreateDirectory(directotyname);
            }

            foreach (var item in SatEph16Dic)
            {
                List<string> DataBuffer = new List<string>();
                string fileName = directotyname + item.Key + "-星历拟合数据.txt";
                SixTeen_EphemerisDataWriter write = new SixTeen_EphemerisDataWriter();
                write.InitSixTeen_EphemerisData(item.Key);
                DataBuffer = write.WriteToStringList(item.Value, satType);
                //File.AppendAllText(fileName, DataBuffer.ToArray());
                File.AppendAllLines(fileName, DataBuffer);
            }
        }

        /// <summary>
        /// 钟差拟合参数存储
        /// </summary>
        public void SaveClockFitData(string directotyname, Dictionary<string, List<ClkErrFitMsg>> ClockErrDic)
        {
            //创建保存数据文件路径及文件
            directotyname = directotyname + "\\主控站\\导航电文参数\\钟差拟合参数\\";
            if (!Directory.Exists(directotyname))
            {
                Directory.CreateDirectory(directotyname);
            }

            foreach (var item in ClockErrDic)
            {
                //_Parent.SatelliteFlagDic[item.Key]. 
                List<string> DataBuffer = new List<string>();
                string fileName = directotyname + item.Key + "-钟差拟合数据.txt";

                DataBuffer.Clear();
                ClockFitDataWriter write = new ClockFitDataWriter();
                write.InitClockFitDataFile(item.Key);
                DataBuffer = write.WriteToStringList(item.Value);
                File.AppendAllLines(fileName, DataBuffer);
            }

        }

        /// <summary>
        /// 电离层拟合数据存储
        /// </summary>
        public void SaveIonFitData(string directotyname, List<IonoFit_OutputMsg> IonoFitOutputMsgList)
        {
            //创建保存数据文件路径及文件

            directotyname = directotyname + "\\主控站\\导航电文参数\\电离层拟合参数\\";
            if (!Directory.Exists(directotyname))
            {
                Directory.CreateDirectory(directotyname);
            }

            EightIonoSphereWriter Writer = new EightIonoSphereWriter();

            string fileName = directotyname + "电离层拟合数据.txt";

            Writer.InitEightIonoSphereDataFile(fileName);

            foreach (var item in IonoFitOutputMsgList)
            {
                IonoSphere_8 Ion8Param = new IonoSphere_8();
                Ion8Param = item.IonoFitOutput.EightIonoData;
                Writer.WriteFile(item.FitDay, Ion8Param.Alpha0, Ion8Param.Alpha1, Ion8Param.Alpha2, Ion8Param.Alpha3, Ion8Param.Beta0, Ion8Param.Beta1, Ion8Param.Beta2, Ion8Param.Beta3);
            }
        }

        void SaveObsTextData(string TextDirectory, ESegmentType segmentType)
        {
            switch (segmentType)
            {
                case ESegmentType.SpaceSegment:
                    break;
                case ESegmentType.GroudSegment:

                    foreach (var subGround in (this.Parent.SegmentColletion[2] as GroundSegment).SubGroundSegmentList)
                    {
                        foreach (var stationList in subGround.GroundList)
                        {
                            if (stationList.Type == EStationType.MonitorStation)
                            {
                                string MonTextDirectory = TextDirectory + "\\" + "监测站" + "\\观测数据\\";
                                if (!Directory.Exists(MonTextDirectory))
                                {
                                    Directory.CreateDirectory(MonTextDirectory);
                                }
                                foreach (var station in stationList.StationList)
                                {
                                    MeasureResultDataWriter obsDataWriter = new MeasureResultDataWriter();
                                    double[] Freq = new double[3];
                                    obsDataWriter.InitCrossLinkDataString(station.Name, Freq);
                                    List<string> dataBuffer = obsDataWriter.WriteString((station as MonitorStation).MonitorReceivers[0].AllSatsObsDataDic);
                                    string obsfilename = MonTextDirectory + station.Name + ".txt";
                                    foreach (var str in dataBuffer)
                                    {
                                        File.AppendAllText(obsfilename, str + "\r\n");
                                    }
                                }
                            }
                        }
                    }
                    break;
                case ESegmentType.UserSegment:
                    break;
                default:
                    break;
            }
        }

        void SaveUserTextData(string TextDirectory, DataSaveFlagModel DataModel)
        {
            UserSegment user = Parent.SegmentColletion[3] as UserSegment;

            if (DataModel.SubModelList[1].IsChecked)
            {
                foreach (var item in user.UserModelList)
                {
                    if (item.Type != EUserType.StaticUser)
                    {
                        string path = TextDirectory + item.Name + "\\";
                        if (!Directory.Exists(path))
                        {
                            Directory.CreateDirectory(path);
                        }
                        path += item.Name + "_轨迹数据.txt";
                        TrajectoryDataWriter dataWriter = new TrajectoryDataWriter();
                        dataWriter.InitTrajectoryDataWriter(item.Name);
                        List<string> DataBuffer = dataWriter.WriteToStringList(((DynamicUser)item).UserTrajectory);
                        foreach (var str in DataBuffer)
                        {
                            File.AppendAllText(path, str + "\r\n");
                        }
                    }
                }
            }
            if ((DataModel.SubModelList[0].IsChecked))
            {
                foreach (var item in user.UserModelList)
                {
                    foreach (var rec in item.RecCollection)
                    {
                        string path = TextDirectory + item.Name + "//";
                        if (!Directory.Exists(path))
                        {
                            Directory.CreateDirectory(path);
                        }
                        path += rec.Name + "_观测数据.txt";
                        MeasureResultDataWriter obsDataWriter = new MeasureResultDataWriter();
                        int freqnum = rec.RecFre.Count;
                        double[] freq = new double[freqnum];
                        obsDataWriter.InitCrossLinkDataString(rec.Name, freq);
                        List<string> DataBuffer = obsDataWriter.WriteString(rec.AllObsSatsDataDic);
                        //List<string> DataBuffer = obsDataWriter.WriteString(rec.ObsSatsDataDic_ConType);
                        foreach (var str in DataBuffer)
                        {
                            File.AppendAllText(path, str + "\r\n");
                        }
                    }
                }
            }
        }

        #endregion
        #endregion

        #region 参数配置执行方法模板
        /// <summary>
        /// XXX 功能命令执行方法
        /// </summary>
        /// <param name="param"></param>
        void ParameterConfig_Execute(object param)
        {
            ParamConfig();
        }

        public bool ParamConfig()
        {
            bool flag = false;
            ScenarioParamConfigWnd paramConfig = new ScenarioParamConfigWnd();
            paramConfig.WindowStartupLocation = System.Windows.WindowStartupLocation.CenterScreen;
            paramConfig.StartTimeStr = Parent.StartTime.ToString();
            paramConfig.StopTimeStr = Parent.EndTime.ToString();
            paramConfig.EpochStr = Parent.EpochTime.ToString();
            paramConfig.SimStep = Parent.StepSize;
            if (paramConfig.ShowDialog() == true)
            {
                UTCTimeClass startTime = new UTCTimeClass();
                startTime.LoadFromDateTime(DateTime.Parse(paramConfig.StartTimeStr));
                Parent.StartTime = startTime;

                UTCTimeClass stopTime = new UTCTimeClass();
                stopTime.LoadFromDateTime(DateTime.Parse(paramConfig.StopTimeStr));
                Parent.EndTime = stopTime;

                UTCTimeClass epochTime = new UTCTimeClass();
                epochTime.LoadFromDateTime(DateTime.Parse(paramConfig.EpochStr));
                Parent.EpochTime = epochTime;

                Parent.StepSize = paramConfig.SimStep;

                //设置完场景时间，就马上初始化环境段数据
                Parent.EnvironmentSegmentInit();
                flag = true;
            }
            return flag;
        }
        /// <summary>
        /// XXX功能命令可执行控制
        /// </summary>
        /// <param name="param"></param>
        /// <returns></returns>
        bool ParameterConfig_CanExecute(object param)
        {
            return CanExecute();
        }


        #endregion

        #region 执行方法模板
        /// <summary>
        /// XXX 功能命令执行方法
        /// </summary>
        /// <param name="param"></param>
        void XXX_Execute(object param)
        {

        }
        /// <summary>
        /// XXX功能命令可执行控制
        /// </summary>
        /// <param name="param"></param>
        /// <returns></returns>
        bool XXX_CanExecute(object param)
        {
            return CanExecute();
        }

        #endregion

        #endregion

        #region 通用可执行判断方法
        private bool CanExecute()
        {
            bool flag = false;
            if (BDSimObject.GlobalStatus == ESimStatus.UnInited || BDSimObject.GlobalStatus == ESimStatus.End)
            {
                flag = true;
            }
            return flag;
        }
        #endregion
    }
}
